<?php

	namespace org\tekuna\framework\action;

	use \Exception;

	use org\tekuna\base\Tekuna;
	
	use org\tekuna\core\application\Application;
	use org\tekuna\core\context\Context;
	use org\tekuna\core\configuration\ConfigurationElement;
	use org\tekuna\core\configuration\ConfigurationException;

	use org\tekuna\framework\RequestDispatchException;

	
	/**
	 * This class handles the matching of a certain CLI action that is defined
	 * in a given component. The action element is matched against the second
	 * command line parameter of the PHP executable (the first one is the script).
	 */
	class CliActionProcessor {

		protected
			$objContext = NULL,
			$objComponentElement = NULL,
			$arrActions = array(),
		
			$objLogger = NULL;
			
		
		/**
		 * Construct a new CliActionProcessor
		 * 
		 * @param Context $objContext the application context
		 * @param ConfigurationElement $objComponentElement the surrounding 
		 *        (already matched) configuration element of the component.
		 */
		public function __construct(Context $objContext, ConfigurationElement $objComponentElement) {

			$this -> objContext = $objContext;
			$this -> objComponentElement = $objComponentElement;

			// TODO: some validation of the actions
			$this -> arrActions = $objComponentElement -> getAllChildElements('framework', 'action');

			$this -> objLogger = Tekuna :: getLogger(__CLASS__);
		}

		
		/**
		 * @return ConfigurationElement returns the configuration element of the matching action
		 * @throws ActionException in case when anything goes wrong
		 * @throws RequestDispatchException whern no matching action was found.
		 */
		public function getMatchingCliAction() {

			foreach ($this -> arrActions as $objAction) {

				try {

					if ($this -> isMatchingCliAction($objAction)) {

						return $objAction;
					}
				}
				catch (Exception $objException) {

					throw new ActionException("Error while matching CLI action ". trim($objAction -> __toString()), -1, $objException);
				}
			}

			throw new RequestDispatchException("No matching CLI action found.");
		}

		
		protected function isMatchingCliAction(ConfigurationElement $objActionElement) {

			$objRequest = $this -> objContext -> getRequest();
			
			// special matching applies when less than 3 parameters are given
			if ($objRequest -> getArgumentCount() <= 1) {
				
				return ! $objActionElement -> hasAttribute('framework', 'first-param');
			}
			elseif ($objRequest -> getArgumentCount() == 2) {
				
				// action without that parameter can't match
				if (! $objActionElement -> hasAttribute('framework', 'first-param')) {
					
					return false;
				}
				
				// get the second command line param
				$sFirstParam = $objRequest -> getArgument(1);
	
				// get the action's first-param attribute
				$sActionFirstParam = $objActionElement -> getAttribute('framework', 'first-param') -> getValue();

				return trim($sFirstParam) === trim($sActionFirstParam);
			}
			else {
				
				// action without that parameter can't match
				if (! $objActionElement -> hasAttribute('framework', 'second-param')) {
					
					return false;
				}
				
				// get the second command line param
				$sSecondParam = $objRequest -> getArgument(2);
	
				// get the action's first-param attribute
				$sActionSecondParam = $objActionElement -> getAttribute('framework', 'second-param') -> getValue();

				return trim($sSecondParam) === trim($sActionSecondParam);
			}
		}
	}

